package com.nit.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.nit.dto.UserCodeDTO;
import com.nit.dto.UserDTO;
import com.nit.dto.utils.OpResultDTO;
import com.nit.entity.UserEntity;
import com.nit.mapper.UserCodeMapper;
import com.nit.mapper.UserMapper;
import com.nit.service.UserService;
import com.nit.utils.JWTUtil;
import com.nit.utils.MD5Util;
import com.nit.utils.SystemConstant;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;
import net.sf.json.JSONArray;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import sun.misc.BASE64Encoder;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.Random;
import java.util.ArrayList;
import java.util.List;


@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper userMapper;
    @Resource
    private UserCodeMapper userCodeMapper;

    @Override
    public JSONObject loginCheck(String userName, String userPwd, String verificationCode, Long ucId) throws Exception {

        JSONObject loginResponse = new JSONObject();

        //验证验证码
        UserCodeDTO userCodeDTO = userCodeMapper.queryByUcId(ucId);
        if (userCodeDTO.getGmtExpire().compareTo(new Date()) <= 0 || userCodeDTO.getIsUsed() == 1) {
            loginResponse.put("status", "error");
            loginResponse.put("reason", "非法验证码");
            return loginResponse;
        }
        if (!userCodeDTO.getUcCode().equals(verificationCode.toUpperCase())){
            loginResponse.put("status", "error");
            loginResponse.put("reason", "验证码错误");
            return loginResponse;
        }

        UserDTO userDTO = userMapper.loginCheck(userName, userPwd);

        if (null == userDTO) {
            loginResponse.put("status", "error");
            loginResponse.put("reason", "用户名或密码错误");
        } else {
            loginResponse.put("status", "ok");
            loginResponse.put("roleName", SystemConstant.USER_ROLE_TYPE[userDTO.getRoleId()]);
            loginResponse.put("token", JWTUtil.sign(userDTO.getUserId().toString()));
            loginResponse.put("userId", userDTO.getUserId());
            loginResponse.put("userName", userDTO.getUserName());
        }

        userCodeMapper.setIsUsed(ucId); //设置验证码已被使用

        return loginResponse;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OpResultDTO register(UserDTO userDTO) throws Exception {

        OpResultDTO opResultDTO = new OpResultDTO();

        if (0 != userMapper.userIsExist(userDTO.getUserName())) {
            opResultDTO.setLongResult(-1L);
            opResultDTO.setObjResult("用户名已存在");
            return opResultDTO;
        }

        userDTO.setUserPwd(MD5Util.getMD5(userDTO.getUserPwd(), true, 16));
        MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
        UserEntity userEntity = mapperFactory.getMapperFacade().map(userDTO, UserEntity.class);
        userEntity.setGmtModified(new Date());
        userEntity.setGmtCreate(new Date());
        userEntity.setRoleId(3);
        userMapper.register(userEntity);
        opResultDTO.setLongResult(userEntity.getUserId());

        return opResultDTO;
    }

    /**
     * @Description: 获取验证码
     * @Author: 张凡
     * @Date: 2019/9/2 16:06
     */
    public OpResultDTO getUserCode() throws Exception {
        OpResultDTO opResultDTO = new OpResultDTO();
        String[] imageAndCode = createImageWithVerifyCode(120, 30, 10);
        Date now = new Date();
        int delta = 300000; //5分钟后验证码过期
        UserCodeDTO userCodeDTO = new UserCodeDTO(imageAndCode[1], 0, new Date(now.getTime() + delta));
        userCodeMapper.add(userCodeDTO);
        opResultDTO.setLongResult(userCodeDTO.getUcId());
        opResultDTO.setObjResult(imageAndCode[0]);
        return opResultDTO;
    }

    /**
     * 生成验证码图片 转 base64 并且保存图片验证码到session里
     *
     * @param width  图片宽度
     * @param height 图片高度
     * @param length 验证码位数
     * @return 图片的base64串
     */
    private static String[] createImageWithVerifyCode(int width, int height, int length) throws IOException {
        String png_base64 = "";
        //绘制内存中的图片
        BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        //得到画图对象
        Graphics graphics = bufferedImage.getGraphics();
        //绘制图片前指定一个颜色
        graphics.setColor(getRandColor(160, 200));
        graphics.fillRect(0, 0, width, height);
        //绘制边框
        graphics.setColor(Color.white);
        graphics.drawRect(0, 0, width - 1, height - 1);
        // 步骤四 四个随机数字
        Graphics2D graphics2d = (Graphics2D) graphics;
        graphics2d.setFont(new Font("宋体", Font.BOLD, 18));
        Random random = new Random();
        /*VerifyCodeUtil vcu = new VerifyCodeUtil();
        String word = vcu.produceNumAndChar(length);*/
        String word = produceNumAndChar(4);
        // 定义x坐标
        int x = 10;
        for (int i = 0; i < word.length(); i++) {
            // 随机颜色
            graphics2d.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));
            // 旋转 -30 --- 30度
            int jiaodu = random.nextInt(60) - 30;
            // 换算弧度
            double theta = jiaodu * Math.PI / 180;
            // 获得字母数字
            char c = word.charAt(i);
            //将c 输出到图片
            graphics2d.rotate(theta, x, 20);
            graphics2d.drawString(String.valueOf(c), x, 20);
            graphics2d.rotate(-theta, x, 20);
            x += 30;
        }

        // 绘制干扰线
        graphics.setColor(getRandColor(160, 200));
        int x1;
        int x2;
        int y1;
        int y2;
        for (int i = 0; i < 30; i++) {
            x1 = random.nextInt(width);
            x2 = random.nextInt(12);
            y1 = random.nextInt(height);
            y2 = random.nextInt(12);
            graphics.drawLine(x1, y1, x1 + x2, x2 + y2);
        }
        graphics.dispose();// 释放资源
        ByteArrayOutputStream baos = new ByteArrayOutputStream();//io流
        ImageIO.write(bufferedImage, "png", baos);//写入流中
        byte[] bytes = baos.toByteArray();//转换成字节
        BASE64Encoder encoder = new BASE64Encoder();
        png_base64 = encoder.encodeBuffer(bytes).trim();
        png_base64 = png_base64.replaceAll("\n", "").replaceAll("\r", "");//删除 \r\n
        String[] codes = {"data:image/png;base64," + png_base64, word};
        return codes;
    }

    /**
     * 生成N位数字和字母混合的验证码
     *
     * @param num 验证码位数
     * @return code 生成的验证码字符串
     */
    private static String produceNumAndChar(int num) {
        Random random = new Random();
        String code = "";
        String ch = "ABCDEFGHIJKLMNPQRSTUVWXYZ";
        String n = "123456789";
        for (int i = 0; i < num; i++) {
            int flag = random.nextInt(2);
            if (flag == 0) {//数字
                code += n.charAt(random.nextInt(n.length()));
            } else {//字母
                code += ch.charAt(random.nextInt(ch.length()));
            }
        }
        return code;
    }

    /**
     * 给定范围获得随机颜色
     *
     * @param fc
     * @param bc
     * @return
     */
    private static Color getRandColor(int fc, int bc) {
        Random random = new Random();
        if (fc > 255)
            fc = 255;
        if (bc > 255)
            bc = 255;
        int r = fc + random.nextInt(bc - fc);
        int g = fc + random.nextInt(bc - fc);
        int b = fc + random.nextInt(bc - fc);
        return new Color(r, g, b);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long remove(String userIds) throws Exception {
        JSONArray jsonArray = JSONArray.fromObject(userIds);
        for (int i = 0; i < jsonArray.size(); i++) {
            userMapper.remove(Long.parseLong(jsonArray.get(i).toString()));
        }
        return Long.parseLong(String.valueOf(jsonArray.size()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long update(UserDTO userDTO) throws Exception {
        return userMapper.update(userDTO).longValue();
    }
   /**
   * @Description: 是否禁用
   * @Author: Lc
   * @Date: 2019/9/8
   */

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long change(String userIds) throws Exception {
        JSONArray jsonArray = JSONArray.fromObject(userIds);
        for (int i = 0; i < jsonArray.size(); i++) {
            userMapper.change(Long.parseLong(jsonArray.get(i).toString()));
        }
        return Long.parseLong(String.valueOf(jsonArray.size()));
    }

    @Override
    public List<UserDTO> query(String userName) throws Exception {

        List<UserDTO> userDTOS = new ArrayList<>();

        userDTOS = userMapper.query(userName);

        return userDTOS;
    }
}
